<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>2048 Game</title>
    <style>
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        margin: 0;
        background-color: #faf8ef;
        font-family: Arial, sans-serif;
      }

      .grid {
        display: grid;
        grid-template-columns: repeat(4, 100px);
        gap: 10px;
      }

      .tile {
        height: 100px;
        display: flex;
        justify-content: center;
        align-items: center;
        background-color: #cdc1b4;
        border-radius: 5px;
        font-size: 32px;
        color: #776e65;
      }

      .tile-2 {
        background-color: #eee4da;
      }

      .tile-4 {
        background-color: #ede0c8;
      }

      .tile-8 {
        background-color: #f2b179;
        color: white;
      }

      .tile-16 {
        background-color: #f59563;
        color: white;
      }

      .tile-32 {
        background-color: #f67c5f;
        color: white;
      }

      .tile-64 {
        background-color: #f65e3b;
        color: white;
      }

      .tile-128 {
        background-color: #edcf72;
        color: white;
      }

      .tile-256 {
        background-color: #edcc61;
        color: white;
      }

      .tile-512 {
        background-color: #edc850;
        color: white;
      }

      .tile-1024 {
        background-color: #edc53f;
        color: white;
      }

      .tile-2048 {
        background-color: #edc22e;
        color: white;
      }

      .score {
        position: absolute;
        top: 20px;
        right: 20px;
        font-size: 24px;
        color: #776e65;
      }

      .game-over {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        background-color: rgba(255, 255, 255, 0.8);
        padding: 20px;
        border-radius: 5px;
        font-size: 24px;
        display: none;
      }
    </style>
  </head>
  <body>
    <div class="score">Score: <span id="score">0</span></div>
    <div class="grid" id="grid"></div>
    <div class="game-over" id="gameOver">
      Game Over!<br />
      <button onclick="restartGame()">Restart</button>
    </div>

    <script>
      const gridSize = 4;
      const tiles = document.getElementById("grid");
      let matrix = [];
      let scoreElement = document.getElementById("score");
      let gameOverElement = document.getElementById("gameOver");
      let score = 0;
      let gameOver = false;

      function createGrid() {
        for (let i = 0; i < gridSize; i++) {
          matrix[i] = [];
          for (let j = 0; j < gridSize; j++) {
            const tile = document.createElement("div");
            tile.classList.add("tile");
            tiles.appendChild(tile);
            matrix[i][j] = 0;
          }
        }
        addRandomTile();
        addRandomTile();
      }

      function addRandomTile() {
        if (isBoardFull()) return;

        let x = Math.floor(Math.random() * gridSize);
        let y = Math.floor(Math.random() * gridSize);
        while (matrix[x][y] !== 0) {
          x = Math.floor(Math.random() * gridSize);
          y = Math.floor(Math.random() * gridSize);
        }
        matrix[x][y] = Math.random() > 0.5 ? 4 : 2;
        updateGrid();
      }

      function updateGrid() {
        const tiles = document.querySelectorAll(".tile");
        tiles.forEach((tile, index) => {
          const x = Math.floor(index / gridSize);
          const y = index % gridSize;
          const value = matrix[x][y];
          tile.textContent = value === 0 ? "" : value;
          const tileClass = `tile-${value}`;
          tile.className = `tile ${tileClass}`;
        });
      }
      function move(direction) {
        if (gameOver) return;

        let changed = false;

        switch (direction) {
          case "up":
            matrix = transpose(matrix);
            changed = swipe(matrix);
            matrix = transpose(matrix);
            break;
          case "down":
            matrix = transpose(matrix).map((row) => row.slice().reverse());
            changed = swipe(matrix);
            matrix = transpose(matrix.map((row) => row.slice().reverse()));
            break;
          case "left":
            changed = swipe(matrix);
            break;
          case "right":
            matrix = matrix.map((row) => row.slice().reverse());
            changed = swipe(matrix);
            matrix = matrix.map((row) => row.slice().reverse());
            break;
        }

        if (changed) {
          addRandomTile();
          checkGameOver();
          scoreElement.textContent = score;
        }
      }

      function swipe(matrix) {
        let changed = false;
        for (let i = 0; i < gridSize; i++) {
          const row = matrix[i];
          let newRow = row.filter((num) => num !== 0);
          let merged = [];
          let j = 0;
          while (j < newRow.length) {
            if (j + 1 < newRow.length && newRow[j] === newRow[j + 1]) {
              merged.push(newRow[j] * 2);
              score += newRow[j] * 2;
              j += 2;
              changed = true;
            } else {
              merged.push(newRow[j]);
              j++;
            }
          }
          merged = merged.concat(new Array(gridSize - merged.length).fill(0));
          matrix[i] = merged;
          if (JSON.stringify(row) !== JSON.stringify(matrix[i])) {
            changed = true;
          }
        }
        return changed;
      }

      function transpose(matrix) {
        let newMatrix = [];
        for (let i = 0; i < gridSize; i++) {
          newMatrix[i] = [];
          for (let j = 0; j < gridSize; j++) {
            newMatrix[i][j] = matrix[j][i];
          }
        }
        return newMatrix;
      }

      function isBoardFull() {
        for (let i = 0; i < gridSize; i++) {
          for (let j = 0; j < gridSize; j++) {
            if (matrix[i][j] === 0) return false;
          }
        }
        return true;
      }

      function checkGameOver() {
        let gameOver = true;
        for (let i = 0; i < gridSize; i++) {
          for (let j = 0; j < gridSize; j++) {
            if (matrix[i][j] === 0) {
              gameOver = false;
            } else if (
              (i > 0 && matrix[i][j] === matrix[i - 1][j]) ||
              (i < gridSize - 1 && matrix[i][j] === matrix[i + 1][j]) ||
              (j > 0 && matrix[i][j] === matrix[i][j - 1]) ||
              (j < gridSize - 1 && matrix[i][j] === matrix[i][j + 1])
            ) {
              gameOver = false;
            }
          }
        }
        if (gameOver) {
          gameOverElement.style.display = "block";
        }
      }

      function restartGame() {
        gameOverElement.style.display = "none";
        score = 0;
        scoreElement.textContent = score;
        matrix = [];
        tiles.innerHTML = "";
        createGrid();
        gameOver = false;
      }

      document.addEventListener("keydown", (e) => {
        switch (e.key) {
          case "ArrowUp":
            move("up");
            break;
          case "ArrowDown":
            move("down");
            break;
          case "ArrowLeft":
            move("left");
            break;
          case "ArrowRight":
            move("right");
            break;
        }
      });

      createGrid();
    </script>
  </body>
</html>
